import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.Integer;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.File;
import java.util.*;

public class Main {

    public int[] getResults(String filename) {

        ArrayList list = new ArrayList();
        try {
            BufferedReader reader = new BufferedReader(new FileReader(filename));

            String line = null;
            while((line=reader.readLine())!=null) {
                String item[] = line.split(",");
                String last = item[item.length - 1];
                int res = Integer.parseInt(last.substring(0, 1));
                list.add(res);
            }
            }
         catch (Exception e) {
            e.printStackTrace();
        }

        int label_info[] = new int[list.size()];
        for(int i=0; i<label_info.length; i++) {
            label_info[i] = (int) list.get(i);
        }
        return label_info;
    }

    public float[] judge(String standardResults, String userCommitFile) {
        // final eval results
        float[] result = new float[9];
        // flag for error true: correct false: have errors
        boolean flag = true;
        
        // the whole predictions
        int[] num_pred = new int[8];
        float[] result_pred = new float[8];
        Arrays.fill(num_pred, 0);
        Arrays.fill(result_pred, 0.0f);

        // Traversal all file in commit dir
        File predFiles = new File(userCommitFile);
        String[] predList = predFiles.list();

        for (int i=0; i<predList.length && flag; i++) {

            String eval_filename = predList[i].substring(0, predList[i].length()-4);

            // get ground truth info
            int gt[] = getResults( standardResults+predList[i]);
            // get pred info
            int pred[] = getResults( userCommitFile+predList[i]);

            // Error: gt is inconsistent with pred points
            if (gt.length != pred.length) {
                flag = false;
                result[0] = 2.0f;
                break;
            }

            //  Calculate each category
            // {'DontCare': 0, 'cyclist': 1, 'tricycle': 2, 'smallMot':3, 'bigMot': 4,
            //  'pedestrian': 5, 'crowds': 6, 'unknown': 7}
            int union[] = new int[8];
            Arrays.fill(union, 0);
            int intersection[] = new int[8];
            Arrays.fill(intersection, 0);

            for(int j=0; j<gt.length; j++) {
                if(pred[j] == gt[j]) {
                    union[pred[j]] = union[pred[j]] + 1;
                    intersection[pred[j]] = intersection[pred[j]] + 1;
                }
                else {
                    union[pred[j]] = union[pred[j]] + 1;
                    union[gt[j]] = union[gt[j]] + 1;
                }
            }

            // statistics iou for each category
            for (int j=1; j<=7; j++) {
                if (union[j] == 0) {
                    continue;
                }
                else {
                    result_pred[j] = result_pred[j] + (float)intersection[j] / (float)union[j];
                    num_pred[j] = num_pred[j] + 1;
                }

            }

        }
        // return results
        for (int i=1; i<=7; i++) {
            result[i] = (num_pred[i] == 0)? 0.0f: result_pred[i] / (float)num_pred[i];
            result[8] = result[i] + result[8];
        }
        if (flag) {
            //result[0] = 0.0f;
            result[8] = result[8] / 7.0f;
        }
        // cyclist:0.0000 tricycle:0.9183 smallMot:0.9544 bigMot:0.0025 pedestrian:0.0000 crowds:0.0000 unknown
        System.out.printf("result back ground : %f \n", result[0]);
        System.out.printf("result cyclist : %f \n", result[1]);
        System.out.printf("result tricycle: %f \n", result[2]);
        System.out.printf("result smallMot: %f \n", result[3]);
        System.out.printf("result bigMot: %f \n", result[4]);
        System.out.printf("result pedestrian: %f \n", result[5]);
        System.out.printf("result crowds: %f \n", result[6]);
        System.out.printf("result unknown: %f \n", result[7]);
        System.out.printf("result average of concern: %f \n", result[8]);
        System.out.printf("result average of concern compute: %f \n", (result[1]+result[2]+result[3]+result[4]+result[5]+result[6]+result[7])/7);
        return result;
    }
    public static void main(String[] args) {
        Main m = new Main();
        //m.judge("gt/",
        //        "pred/");
        m.judge("../data_3d_pts_lit/training/category/",
                "../model_out/");
    }

}
